package com.programs.waw;

import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.util.Log;

public class AliceAlgorithm {

	static final String alis = new String(
			"64C6DDE3E579B6D986968D3445D23B15CAAF128402AC560005CE2075913FDCE8");

	static final char[] charSet = { '0', '1', '2', '3', '4', '5', '6', '7',
			'8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
			'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
			'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
			'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
			'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
			'1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',
			'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
			'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
			'4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
			'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
			'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
			'7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
			'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
			'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
			'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c',
			'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
			'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2',
			'3' };

	private String ssid;
	private ArrayList<AliceData> aliceList;

	public AliceAlgorithm(String ssid, InputStream is) {
		this.ssid = ssid;

		ReadAliceDatas r = new ReadAliceDatas();
		r.read(is, ssid.substring(0, 3));
		aliceList = r.getList();
	}

	public ArrayList<AliceData> getList() {
		return aliceList;
	}

	public ArrayList<AliceData> getCleanList() {

		ArrayList<AliceData> l = new ArrayList<AliceData>();

		for (AliceData a : aliceList) {

			if (a.getMac().length() < 12 || a.getSn().contains("-")
					|| a.getSn().contains(",")) {
				Log.e("Serie errate", a.toString());
				continue;
			}

			l.add(a);
		}

		return l;
	}

	public ArrayList<AliceData> getCleanNoRepeatList() {

		HashMap<String, AliceData> hm = new HashMap<String, AliceData>();
		ArrayList<AliceData> list = new ArrayList<AliceData>();

		for (AliceData a : aliceList) {

			if (a.getMac().length() < 12 || a.getSn().contains("-")
					|| a.getSn().contains(",")) {
				Log.e("Serie errate", a.toString());
				continue;
			}

			if (ssid.startsWith(a.getSsid())) {
				list.add(a);
			}

			hm.put(a.getWpa(), a);
		}

		for (AliceData a : list) {
			hm.put(a.getWpa(), a);
		}

		return new ArrayList<AliceData>(hm.values());
	}

	public void Calcola(boolean isWep) {

		try {
			MessageDigest md = MessageDigest.getInstance("SHA-256");

			for (AliceData aliceData : aliceList) {
				CalcolaMac(aliceData, ssid);
				CalcolaSeriale(aliceData, ssid);
				CalcolaWpa(aliceData, md, isWep);

				Log.i("Alg", aliceData.toString());
			}
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			Log.e("exception", e.toString());
		}

	}

	private void CalcolaMac(AliceData a, String ssid) {

		for (int i = 0; i < 3; i++) {

			String macPartial = Integer.toHexString(Integer.parseInt(i + ssid));

			if (macPartial.length() > 7) {
				macPartial = macPartial.substring(macPartial.length() - 7);
				System.out.println(macPartial);
			}

			if (LastEqualFirst(a.getMac(), macPartial)) {
				macPartial = macPartial.substring(1);
				a.setMac(a.getMac() + macPartial);
				return;
			}
		}
	}

	private void CalcolaSeriale(AliceData a, String ssid) {
		double snPartial = (Double.parseDouble(ssid) - a.getQ()) / a.getK();

		DecimalFormat df = new DecimalFormat("0.##");
		String sn = df.format(snPartial);

		for (int i = sn.length(); i < 7; i++) {
			sn = "0" + sn;
		}

		a.setSn(a.getSn() + "X" + sn);
	}

	private void CalcolaWpa(AliceData a, MessageDigest md, boolean isWep) {

		byte[] alisByte = StrHexToByte(alis);
		byte[] snByte = a.getSn().getBytes();
		byte[] macByte = StrHexToByte(a.getMac());

		byte[] hash = ConcatArrayByte(ConcatArrayByte(alisByte, snByte),
				macByte);
		byte[] byteArray = md.digest(hash);

		String hexIndex = ByteArrayToHexString(byteArray);

		int index;
		StringBuilder sb = new StringBuilder();

		int pwdLength;

		if (isWep) {
			pwdLength = 26;
		} else {
			pwdLength = 48;
		}

		for (int i = 0; i < pwdLength; i += 2) {
			index = Integer.parseInt(hexIndex.substring(i, i + 2), 16);
			sb.append(charSet[index]);
		}

		a.setWpa(sb.toString());

	}

	private boolean LastEqualFirst(String s1, String s2) {
		s1 = s1.toUpperCase();
		s2 = s2.toUpperCase();

		if (s1.toCharArray()[s1.length() - 1] == s2.toCharArray()[0])
			return true;

		return false;
	}

	private byte[] StrHexToByte(String s) {
		ArrayList<Byte> b = new ArrayList<Byte>();

		for (int i = 0; i < s.length(); i += 2)
			b.add((byte) Integer.parseInt(s.substring(i, i + 2), 16));

		return ConvertToByteArray(b);

	}

	private byte[] ConvertToByteArray(List<Byte> list) {

		int size = list.size();

		Byte[] listArray = new Byte[size];
		byte[] b = new byte[size];

		listArray = list.toArray(listArray);

		for (int i = 0; i < size; i++) {
			b[i] = listArray[i];
		}

		return b;
	}

	private String ByteArrayToHexString(byte[] byteArray) {

		StringBuilder hexStringBuilder = new StringBuilder();
		String s;

		for (int i = 0; i < byteArray.length; i++) {

			s = Integer.toHexString(0xFF & byteArray[i]);

			while (s.length() < 2)
				s = "0" + s;

			hexStringBuilder.append(s);

		}

		return hexStringBuilder.toString();
	}

	private byte[] ConcatArrayByte(byte[] a, byte[] b) {

		byte[] c = new byte[a.length + b.length];

		System.arraycopy(a, 0, c, 0, a.length);
		System.arraycopy(b, 0, c, a.length, b.length);

		return c;

	}

}
